#include "../include/SocketIO.hpp"
#include <sys/socket.h>
#include <iostream>
using std::cout;
using std::endl;
namespace wd{


SocketIO:: SocketIO(int netfd)
    :_fd(netfd)
{}


int SocketIO::sendn(const char * buff, int len){
    int left = len;
    const char * pbuf = buff;
    while(left > 0){
        int ret = send(_fd,pbuf,left,0);
        if(ret == -1){
            perror("send");
            return ret;
        }else{
            left -= ret;
            pbuf += ret;
        }
    }
    //正常的len长度的数据
    return len;

}

int SocketIO::recvn(char * buff, int len){
    int left = len;
    char * pbuf = buff;
    while(left > 0){
        int ret = recv(_fd,pbuf,left,0);
        if(ret == -1 && errno == EINTR){
            continue;
        }else if(ret == -1){
            perror("recv");
            return ret;
        }else if(ret == 0){
            return len - left;
        }else{
            left -= ret;
            pbuf += ret;
        }
    }
    //正常读取完所需的len长度的数据
    return len;

}

int SocketIO::readline(char * buff, int max){
    //获取一行数据,以\n结束
    int left = max -1;
    char * pbuf = buff;
    int total = 0;  //表示读取的总的字节数
    
    while(left > 0){
        int ret = recvPeek(pbuf,left); //从内核接收缓冲区中拷贝一份数据到buff

        //查找\n
        for(int i = 0; i < ret; ++i){
            
            if(pbuf[i] == '\n'){
                int sz = i + 1;
                ret = recvn(pbuf,sz);
                total += ret;
                pbuf[i] = '\0';
                return total;
            }

        }

        //这次没有找到'\n',从内核中将数据拿走
        ret = recvn(pbuf,ret);
        left -= ret;
        pbuf += ret;
        total += ret;
    }

    buff[max - 1] = '\0';
    return max - 1;


}

int SocketIO::recvPeek(char * buff, int maxlen){
    int ret = 0;
    do{
        ret = recv(_fd,buff,maxlen,MSG_PEEK);
    }while(ret == -1 && errno == EINTR);

    if(ret < 0){
        perror("recv");
    }

    return ret;

}

int SocketIO::readPacket(Packet & packet){
    
   int type, length;  
   recvn((char*)&type,sizeof(type)); //将TLV的type放到type中
   recvn((char*)&length,sizeof(length));

   if(length > 0){
       //用于存放TLV格式中的data部分
       char * pbuf = new char[length + 1]();
       int ret = recvn(pbuf,length);

       printf("SockIO: pbuf = %s\n",pbuf);

       packet.type = type;
       packet.length = length;
       packet.msg.assign(pbuf,length); //将pbuf的数据拷贝到packet的msg中

       delete [] pbuf;
       return ret + 8; //加8包括type和length两个int
   }
   return 8;
   
}











} //end of namespace wd
